<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <script src='lib/webgl-utils.js'></script>
    <script src='lib/webgl-debug.js'></script>
    <script src='lib/cuon-utils.js'></script>
    <script src='lib/cuon-matrix.js'></script>
</head>
<body onload="main()">
<canvas id="mybox" width="500" height="400">
    请更换新版浏览器查看效果!
</canvas>
<script >
 let VSHADER_SOURCE=`
 attribute vec4 a_position;
 attribute vec4 a_normal;
 uniform mat4 u_mvpMatrix;
 uniform mat4 u_normalMatrix;
 varying vec4 v_color;
 void main(){
     gl_Position=u_mvpMatrix*a_position;
     vec3 lightDirection=normalize(vec3(0.0,0.5,0.7));
     vec4 color=vec4(1.0,0.4,0.0,1.0);
     vec3 normal=normalize((u_normalMatrix*a_normal).xyz);
     float nDotL=max(dot(normal,lightDirection),0.0);
     v_color=vec4(color.rgb*nDotL+vec3(0.1),color.a);
 }
 `

    let FSHADER_SOURCE=
    '#ifdef GL_ES\n' +
  'precision mediump float;\n' +
  '#endif\n' +
  'varying vec4 v_color;\n' +
  'void main() {\n' +
  '  gl_FragColor = v_color;\n' +
  '}\n';

    function main(){
        let canvas=document.getElementById('mybox')
        let gl=getWebGLContext(canvas)
        if (!gl) {
            console.log('Failed to get the rendering context for WebGL');
            return;
        }
        // debugger;
        if(!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)){
            console.log('初始化shader失败');
            return;
        }
        let n=initVertexBuffers(gl);
        if(n<0){
            console.log('faild to set vertex information');
            return;
        }
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.enable(gl.DEPTH_TEST);

        let u_mvpMatrix=gl.getUniformLocation(gl.program,'u_mvpMatrix');
        let u_normalMatrix=gl.getUniformLocation(gl.program,'u_normalMatrix');
        if(!u_mvpMatrix||!u_normalMatrix){
            console.log('failed to get storage location');
            return;
        }
        var viewProjMatrix=new Matrix4();
        viewProjMatrix.setPerspective(50.0,canvas.width/canvas.height,1.0,100.0);
        viewProjMatrix.lookAt(20.0,10.0,30.0,0.0,0.0,0.0,0.0,1.0,0.0);

        document.onkeydown=function(e){
            keydown(e,gl,n,viewProjMatrix,u_mvpMatrix,u_normalMatrix);
        }
        draw(gl,n,viewProjMatrix,u_mvpMatrix,u_normalMatrix)
    }


    let ANGLE_STEP=3.0;
    let g_arm1Angle=-90.0;
    let g_joint1Angle=0.0;
    function keydown(e,gl,n,viewProjMatrix,u_mvpMatrix,u_normalMatrix){
        switch(e.keyCode){
            case 38:
            if(g_joint1Angle<135.0){
                g_joint1Angle+=ANGLE_STEP;
            }
            break;
            case 40:
            if(g_joint1Angle>-135.0){
                g_joint1Angle-=ANGLE_STEP;
            }    
            break;
            case 39:
            g_arm1Angle=(g_arm1Angle+ANGLE_STEP)%360;
            break;
            case 37:
            g_arm1Angle=(g_arm1Angle-ANGLE_STEP)%360;
            break;
            default:return;
        }
        draw(gl,n,viewProjMatrix,u_mvpMatrix,u_normalMatrix);
    }
    function initVertexBuffers(gl){
    var vertices = new Float32Array([
        1.5, 10.0, 1.5, -1.5, 10.0, 1.5, -1.5,  0.0, 1.5,  1.5,  0.0, 1.5, // v0-v1-v2-v3 front
        1.5, 10.0, 1.5,  1.5,  0.0, 1.5,  1.5,  0.0,-1.5,  1.5, 10.0,-1.5, // v0-v3-v4-v5 right
        1.5, 10.0, 1.5,  1.5, 10.0,-1.5, -1.5, 10.0,-1.5, -1.5, 10.0, 1.5, // v0-v5-v6-v1 up
        -1.5, 10.0, 1.5, -1.5, 10.0,-1.5, -1.5,  0.0,-1.5, -1.5,  0.0, 1.5, // v1-v6-v7-v2 left
        -1.5,  0.0,-1.5,  1.5,  0.0,-1.5,  1.5,  0.0, 1.5, -1.5,  0.0, 1.5, // v7-v4-v3-v2 down
        1.5,  0.0,-1.5, -1.5,  0.0,-1.5, -1.5, 10.0,-1.5,  1.5, 10.0,-1.5  // v4-v7-v6-v5 back
    ]);

  // Normal
  var normals = new Float32Array([
    0.0, 0.0, 1.0,  0.0, 0.0, 1.0,  0.0, 0.0, 1.0,  0.0, 0.0, 1.0, // v0-v1-v2-v3 front
    1.0, 0.0, 0.0,  1.0, 0.0, 0.0,  1.0, 0.0, 0.0,  1.0, 0.0, 0.0, // v0-v3-v4-v5 right
    0.0, 1.0, 0.0,  0.0, 1.0, 0.0,  0.0, 1.0, 0.0,  0.0, 1.0, 0.0, // v0-v5-v6-v1 up
   -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // v1-v6-v7-v2 left
    0.0,-1.0, 0.0,  0.0,-1.0, 0.0,  0.0,-1.0, 0.0,  0.0,-1.0, 0.0, // v7-v4-v3-v2 down
    0.0, 0.0,-1.0,  0.0, 0.0,-1.0,  0.0, 0.0,-1.0,  0.0, 0.0,-1.0  // v4-v7-v6-v5 back
  ]);

  // Indices of the vertices
  var indices = new Uint8Array([
     0, 1, 2,   0, 2, 3,    // front
     4, 5, 6,   4, 6, 7,    // right
     8, 9,10,   8,10,11,    // up
    12,13,14,  12,14,15,    // left
    16,17,18,  16,18,19,    // down
    20,21,22,  20,22,23     // back
  ]);

  if(!initArrayBuffer(gl,'a_position',vertices,gl.FLOAT,3)){
      return -1;
  }
  if(!initArrayBuffer(gl,'a_normal',normals,gl.FLOAT,3)){
      return -1;
  }
  gl.bindBuffer(gl.ARRAY_BUFFER,null);
  let indexBuffer=gl.createBuffer();
  if(!indexBuffer){
    console.log('Failed to create the buffer object');
    return -1;
  }
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indices,gl.STATIC_DRAW);
  return indices.length;


    }

    function initArrayBuffer(gl,attribute,data,type,num){
        let buffer=gl.createBuffer();
        if(!buffer){
            console.log('failed to create buffer');
            return false;
        }
        gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
        gl.bufferData(gl.ARRAY_BUFFER,data,gl.STATIC_DRAW);

        let a_attribute=gl.getAttribLocation(gl.program,attribute);
        if(a_attribute<0){
            console.log('Failed to get the storage location of ' + attribute);
            return false;
        }
        gl.vertexAttribPointer(a_attribute,num,type,false,0,0);
        gl.enableVertexAttribArray(a_attribute);
        return true;
    }
    var g_modelMatrix = new Matrix4(), g_mvpMatrix = new Matrix4();
    function draw(gl,n,viewProjMatrix,u_mvpMatrix,u_normalMatrix){
        gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFET_BIT);
        let arm1Length=10.0;
        g_modelMatrix.setTranslate(0.0,-12.0,0.0);
        g_modelMatrix.rotate(g_arm1Angle,0.0,1.0,0.0);
        drawBox(gl,n,viewProjMatrix,u_mvpMatrix,u_normalMatrix);

        g_modelMatrix.translate(0.0,arm1Length,0.0);
        g_modelMatrix.rotate(g_joint1Angle,0.0,0.0,1.0);
        g_modelMatrix.scale(1.3,1.0,1.3);
        drawBox(gl,n,viewProjMatrix,u_mvpMatrix,u_normalMatrix);
    }

    let g_normalMatrix=new Matrix4();
    function drawBox(gl,n,viewProjMatrix,u_mvpMatrix,u_normalMatrix){
        g_mvpMatrix.set(viewProjMatrix);
        g_mvpMatrix.multiply(g_modelMatrix);
        gl.uniformMatrix4fv(u_mvpMatrix,false,g_mvpMatrix.elements);
        g_normalMatrix.setInverseOf(g_modelMatrix);
        g_normalMatrix.transpose();
        gl.uniformMatrix4fv(u_normalMatrix,false,g_normalMatrix.elements);
        gl.drawElements(gl.TRIANGLES,n,gl.UNSIGNED_BYTE,0);
    }


</script>

</body>
</html>